<?php
/*
 * @Descripttion: 
 * @version: v1
 * @Author: Terry
 * @Date: 2021-10-08 11:46:51
 * @LastEditors: Terry
 * @LastEditTime: 2024-12-10 00:28:52
 */
declare (strict_types = 1);

namespace app\video\controller\admin\v1;

use think\Request;
use think\facade\Db;
use libs\Dictionary;
use app\video\extend\libs\TengXunYun;
class Camera {
  

    /**
     * @Descripttion:获取摄像头列表 
     * @Author: Terry
     * @Date: 2021-09-28 18:38:50
     * @param {*}
     */
    public function getList(Request $request){
        $data = $request->data;
        $searchWhere = [
            ['isDelete','=',0],
            ['projectCode','=', $request->prjCode],
            ['level','=',1 ]
        ];

        if(!empty($data['name'])) array_push($searchWhere,['name','like',$data['name'].'%']);
        if(!empty($data['configUuid'])) array_push($searchWhere,['configUuid','=',$data['configUuid']]);
        if(!empty($data['type'])) array_push($searchWhere,['type','=',$data['type']]);

        $list = DB::table('video_projectCamera')
        ->where($searchWhere)
        ->field(['name','connection','number','remark','channelNo','uuid','module','isShow','type','level','configUuid','picUrl','lastHeartDate'])
        ->page((int)$data['page'],(int)$data['limit'])
        ->order('id','DESC')
        ->select()->toArray();

        foreach($list as $key => $value){
            $list[$key]['hasChildren'] = $value['type'] == 01 && $value['level'] == 1;
        }

        $count =  DB::table('video_projectCamera')
        ->where($searchWhere)
        ->count('id');
        $data = [ 
            'list'=>$list,
            'count'=>$count,
        ];
        return result(SUCCESS,$data,'');
    }

    /**
     * @Description:从视频平台重新拉子通道数据
     * @Author: Terry
     * @Date: 2024-08-02 11:16:10
     * @param {Request} $request
     */    
    public function refreshChannel(Request $request){
        $data = $request->data;
        $uuid = $data['uuid'];
        $cameraData = DB::table('video_projectCamera')->where(['uuid'=>$uuid,'projectCode'=>$request->prjCode])->field(['configUuid','id','number'])->find();
        if(!$cameraData)  return result(FAIL,[],'設備有誤，請返回后重試');
        $this->getToken($request->prjCode,$cameraData['configUuid']);
        $channelData = $this->sdk->getChannelNo($cameraData);
        if($channelData['code'] == '200'){
            foreach ($channelData['data'] as $key => $value) {
                DB::table('video_projectCamera')->where(['pNumber'=>$cameraData['number'],'channelNo'=>$value['channelNo']])
                ->update([
                    'name'=>$value['channelName'],
                    'connection'=>$value['status'],
                    'picUrl'=>$value['picUrl'],
                ]);
            }
            return result(SUCCESS,[],'刷新成功!');
        }
        return result(FAIL,[],'刷新失败,请重试');
    }   
    /**
     * @Description: 子通道列表
     * @Author: Terry
     * @Date: 2024-08-02 11:16:20
     * @param {Request} $request
     */    
    public function getChannelList(Request $request){
        $data = $request->data;
        $uuid = $data['uuid'];
        $cameraData = DB::table('video_projectCamera')->where(['uuid'=>$uuid,'projectCode'=>$request->prjCode])->field(['number','type'])->find();
        if(!$cameraData)  return result(FAIL,[],'設備有誤，請返回后重試');
        $where = [           
            ['pNumber','=',$cameraData['number']],
            ['isDelete','=',0],
            ['projectCode','=',$request->prjCode],
            ['level','=',$cameraData['type'] == '01' ? 2 : 1],
        ];
        
        if(isset($data['name']) && $data['name']) array_push($where,['name','like','%'.$data['name'].'%']);

        $list = DB::table('video_projectCamera')
        ->where($where)
        ->field(['name','connection','remark','channelNo','uuid','isShow','module','configUuid','type','picUrl','lastHeartDate'])
        ->order('channelNo')
        ->page((int)$data['page'],(int)$data['limit'])
        ->select()
        ->toArray();

        $count = DB::table('video_projectCamera')
        ->where($where)
        ->count();

        $data  = compact('list','count');

        return result(SUCCESS,$data,'');
    }
         /**
     * @Description: 非接口,用于获取子通道数据的
     * @Author: Terry
     * @Date: 2024-07-26 20:39:03
     * @param {*} $otherWhere
     * @param {*} $otherWhere
     */    
    private function getChannel($pidWhere,$otherWhere=[]){
        $pid = DB::table('video_projectCamera')->where($pidWhere)->value('id');
        if(!$pid) return false;

        $where = [
            'pid'=>$pid,
            'isDelete'=>0,
            'projectCode'=>$pidWhere['projectCode']
        ];

        $where = array_merge($where,$otherWhere);
        $channelData = DB::table('video_projectCamera')
        ->where($where)
        ->field(['name','connection','pNumber as number','remark','channelNo','uuid','isShow','type','module','configUuid'])
        ->order('channelNo')
        ->select()
        ->toArray();
        return $channelData;
    }
    /**
     * @Descripttion: 获取摄像头/nvr 通道信息(視頻監控左侧栏使用)
     * @Author: Terry
     * @Date: 2021-09-30 15:32:33
     * @param {*}
     */    
    public function getChannelData(Request $request){
        $data = $request->data;
        $uuid = $data['uuid'];
        $channelData = $this->getChannel(['uuid'=>$uuid,'projectCode'=>$request->prjCode],['isShow'=>1]);
        if(!$channelData)  return result(FAIL,[],'設備有誤，請返回后重試');
        $token = $this->getToken($request->prjCode,$channelData[0]['configUuid']);
        foreach($channelData as $key => $value){
            $channelData[$key]['token'] = $this->sdk->getPlayerToken($value['number'],$value['channelNo'],'live');
        }
        return result(SUCCESS,$channelData,'');
    }
/**
     * @Descripttion: 设备添加
     * @Author: Terry
     * @Date: 2021-09-28 18:38:59
     * @param {*}
     */    
    public function create(Request $request) {
        $data = $request->data;
        $data['projectCode'] = $request->prjCode;
        $token =  $this->getToken($request->prjCode,$data['configUuid']);
        if(!$token) return result(FAIL,'','请先配置摄像头帐号appKey和appSecret,如已配置请检查是否有误');
        $check = DB::table('video_projectCamera')->where(['number'=>$data['number'],'isDelete'=>0])->field(['projectCode','id'])->find();
        if(!empty($check)&&$request->prjCode!=$check['projectCode']) return result(FAIL,'','该设备已被其他项目绑定,请先解绑');
        if(!empty($check)) return result(FAIL,'','该设备已添加,请勿重复添加');
        DB::startTrans();
        $insertRes = false;
        try {
            $msg  = '添加失败,请重试';
            //把摄像头加入萤石云
            if($data['type']=='02'){
                $createRes = $this->sdk->getChannelNo($data);
                if($createRes['code']==200){
                    $createData = $createRes['data'][0];
                    $ipcData = [
                        'projectCode'=>$data['projectCode'],
                        'name'=>$createData['channelName'],
                        'number'=>$data['number'],
                        'connection'=>$createData['status'],
                        'channelNo'=>$createData['channelNo'],
                        'pNumber'=>$data['number'],
                        'uuid'=>createUuid(),
                        'picUrl'=>$createData['picUrl'],
                        'configUuid'=>$data['configUuid'],
                        'isShow'=>1,
                        'level'=>1,
                        'type'=>$data['type'],
                        'module'=>$data['module'],
                    ];
                    $insertRes = DB::table('video_projectCamera')->insert($ipcData);
                    if($insertRes) $insertRes = $ipcData;
                }
            }else{
                $createRes = $this->sdk->create($data);
                if($createRes['code']===200) $insertRes = $this->cameraInsertToBase($createRes['data'],$request,$data['configUuid']);
            }
            if($insertRes){
                DB::commit();
                $govData = array_merge($data,$createRes);
                // governmentSync($request->prjCode,'cameraCreate',$govData);
                return result(SUCCESS,$insertRes,'添加成功');
            }
            $msg  =  $createRes['message'];
            DB::rollback();
        } catch (\Exception $e) {
            // dd($e->getMessage());
          // 回滚事务
          DB::rollback();
        }
        return result(FAIL,'',$msg);
    }
    /**
     * @Descripttion: 设备添加入数据库
     * @Author: Terry
     * @Date: 2021-09-30 13:25:18
     * @param {*}
     */
    private function cameraInsertToBase($data,$request,$configUuid){
        $formData = $request->data;
        $children = $data['children'];
        unset($data['children']);
        $data['projectCode'] = $request->prjCode;
        $data['configUuid'] = $configUuid;
        $data['type'] = $formData['type'];
        $data['module'] = $formData['module'];

        $pid = DB::table('video_projectCamera')->insertGetId($data);
        if(!$pid) return false;
        $res = [
            'id'=>$pid,
            'name'=>$data['name'],
            'uuid'=>$data['uuid'],
            'hasChildren'=>true,
            'connection'=>$data['connection'],
            'channelNo'=>$data['channelNo'],
            'isShow'=>$data['isShow'],
            'level'=>$data['level'],
            'type'=>$formData['type'],
            'module'=>$formData['module'],
        ];

        if(count($children)==1){
            $res['hasChildren'] = false;
            return $res;
        }  
        foreach($children as $key => $value) {
            $value['pid'] =  $pid;
            $value['projectCode'] =  $request->prjCode;
            $value['configUuid'] =  $configUuid;
            $value['type'] =  $formData['type'];
            $value['module'] =  $formData['module'];
            $channelList[] = dataMerge($request->uuid,$value);
        }
        if(DB::table('video_projectCamera')->insertAll($channelList)) return $res;
        return false;
    }


    /**
     * @Descripttion: 设备更新
     * @Author: Terry
     * @Date: 2021-09-28 18:39:06
     * @param {*}
     */    
    public function update(Request $request) {
        $data = $request->data;
        $token =  $this->getToken($request->prjCode,$data['configUuid']);
        // if(!$token) return result(FAIL,'','请先配置摄像头帐号appKey和appSecret,如已配置请检查是否有误');
        $searchWhere = [
            ['projectCode','=',$request->prjCode],
            ['isDelete','=',0],
            ['uuid','<>',$data['uuid']],
            ['name','=',$data['name']],
        ];
        $nameCheck = DB::table('video_projectCamera')->where($searchWhere)->value('id');
        if(!empty($nameCheck)) return result(FAIL,'','该设备名称已存在');

        unset($searchWhere[3]);
        $searchWhere[2] = ['uuid','=',$data['uuid']];
        $cameraData = DB::table('video_projectCamera')->where($searchWhere)->field(['name','number','level','channelNo','pNumber','type','module','id'])->find();
        if(empty($cameraData)) return result(FAIL,'','修改失败,设备信息有误');

        $res = DB::table('video_projectCamera')
        ->where($searchWhere)
        ->update([
            'name'=>$data['name'],
            'remark'=>$data['remark'] ?? '',
            'module'=>$data['module'],
            'type'=>$data['type'],
            'configUuid'=>$data['configUuid'],
        ]);
        if($cameraData['level'] == 1 && $cameraData['type'] == '01' ){
            DB::table('video_projectCamera')
            ->where(['pid'=>$cameraData['id']])
            ->update([
                'module'=>$data['module'],
                'configUuid'=>$data['configUuid'],
            ]); 
        }
        
        if($cameraData['name'] !== $data['name'] && $token){
            if($cameraData['level']==1) $this->sdk->updateDeviceName($cameraData,$data['name']);
            else  $this->sdk->updateChannelName($cameraData,$data['name']);
        }
        return result(SUCCESS,'','设备信息更新成功');
        
    }   

    /**
     * @description: 获取nvr所有通道信息
     * @Author: Terry
     * @Date: 2022-02-16 15:23:56
     * @param {*}
     */    
    public function getNvrChannel(Request $request){
        $data = $request->data;
        $searchWhere = [
            ['projectCode','=',$request->prjCode],
            ['isDelete','=',0],
            ['uuid','=',$data['uuid']],
        ];
        
        $cameraData = DB::table('video_projectCamera')->where($searchWhere)->field(['id','number','level','type','configUuid','module'])->find();
        if(empty($cameraData)) return result(FAIL,'','设备信息有误请重试！');
        if($cameraData['type']!=='01' && $cameraData['level']!=1) return result(FAIL,'','必须为nvr设备才可获取通道信息');

        $token =  $this->getToken($request->prjCode,$cameraData['configUuid']);
        if(!$token) return result(FAIL,'','请先配置摄像头帐号appKey和appSecret,如已配置请检查是否有误');

        $getChannelNoRes = $this->sdk->getChannelNo($cameraData);
        if($getChannelNoRes['code']==200){
            $searchWhere[2] = ['pid','=',$cameraData['id']];
            $exist = DB::table('video_projectCamera')->where($searchWhere)->column(['channelNo']);
            $channels = array_column($getChannelNoRes['data'],'channelNo');
            $needCreate = array_diff($channels,$exist);

            foreach($needCreate as $key => $value) {
                $channelData = $getChannelNoRes['data'][$key];
                $channel = [
                    'name'=>$channelData['channelName'],
                    'connection'=>$channelData['status'],
                    'level' => 2,
                    'pid' => $cameraData['id'],
                    'projectCode' => $request->prjCode,
                    'isDelete' => 0,
                    'number' => $channelData['ipcSerial'],
                    'channelNo' => $channelData['channelNo'],
                    'uuid' => createUuid(),
                    'pNumber' => $channelData['deviceSerial'],
                    'module' => $cameraData['module'],
                    'type' => $cameraData['type'],
                    'configUuid' => $cameraData['configUuid'],
                    'isShow' => $channelData['status']==1 ? 1 : 0,
                ];
                $channelList[] = dataMerge($request->uuid,$channel);
            }
            if(empty($channelList)) return result(SUCCESS,'','获取成功');
            if(DB::table('video_projectCamera')->insertAll($channelList)) return result(SUCCESS,'','获取成功');
            return result(FAIL,'','获取失败');
        }
    }

    /**
     * @description: 获取摄像头信息
     * @Author: Terry
     * @Date: 2022-02-15 18:34:45
     * @param {*}
     */    
    public function getCameraDetail(Request $request){
        $data = $request->data;
        $uuid =  $data['uuid'];
        $data = DB::table('video_projectCamera')
        ->where([
            'projectCode'=>$request->prjCode,
            'uuid'=>$uuid,
            'isDelete'=>0,
        ])
        ->field(['configUuid as token','pNumber as number','channelNo','number as nvrNumber','pid','name'])
        ->find();
        if($data['pid'] == 0) $data['number'] = $data['nvrNumber'];
        unset($data['nvrNumber'],$data['pid']);
        if(!$data)return result(FAIL,[],'数据有误，获取失败');
        $token = $this->getToken($request->prjCode,$data['token']);
        $data['token'] = $this->sdk->getPlayerToken($data['number'],$data['channelNo'],'rec');
        return result(SUCCESS,$data,'');
    }

    /**
     * @description: 修改摄像头显示状态
     * @Author: Terry
     * @Date: 2022-02-15 19:14:13
     * @param {Request} $request
     */
    public function changeStatus(Request $request){
        $data = $request->data;
        $uuid =  $data['uuid'];

        $singleWhere = $nvrWhere = [
            ['projectCode','=',$request->prjCode],
            ['uuid','=',$data['uuid']],
            ['isDelete','=',0],
        ];
        $where = [
            $singleWhere,
        ];
        
        $cameraData = DB::table('video_projectCamera')
        ->where($where)
        ->field(['pid','id','type','level','configUuid','pNumber','channelNo'])
        ->find();
        
        //关闭nvr 需要把通道一并关闭
        if($cameraData['type']=='01'&&$cameraData['level']==1&&$data['isShow']==0) {
            $nvrWhere[1] = ['pid','=',$cameraData['id']];
            array_push($where,$nvrWhere);
        }
        //开启通道，如果nvr本来是关闭的 需要把nvr也开启
        if($cameraData['type']=='01'&&$cameraData['level']==2&&$data['isShow']==1) {
            $nvrWhere[1] = ['id','=',$cameraData['pid']];
            array_push($where,$nvrWhere);
        }
        DB::startTrans();
        try {
            if($cameraData['level']==2){
                $this->getToken($request->prjCode,$cameraData['configUuid']);
                $cameraData['isShow'] = $data['isShow'];
                $changeRes = $this->sdk->changeShow($cameraData);
            }
            DB::table('video_projectCamera')
            ->whereOr($where)
            ->update(['isShow'=>$data['isShow']]);
            DB::commit();
            return result(SUCCESS,'','修改成功');
        } catch (\Exception $e) {
            dd($e->getMessage());
          // 回滚事务
          DB::rollback();
          return result(FAIL,'','修改失败');
        }
    }
    /**
     * @description: 获取字典表
     * @Author: Terry
     * @Date: 2022-02-16 10:52:50
     * @param {*}
     */    
    public function getDic(Request $request){
        $data = Dictionary::getDic(['cameraModule','cameraType']);
        $data['config'] = DB::table('video_projectCameraConfig')
        ->where([
            'projectCode'=>$request->prjCode,
            'isDelete'=>0,
        ])
        ->field(['name','uuid'])
        ->select();
        return result(SUCCESS,$data,'');
    }
 
    /**
     * @Descripttion: 设备删除
     * @Author: Terry
     * @Date: 2021-09-28 18:39:12
     * @param {*}
     */    
    public function destroy(Request $request) {
        $data = $request->data;
        $uuid = $data['uuid'];
        $cameraData = DB::table('video_projectCamera')->where('uuid',$uuid)->field(['number','id','configUuid'])->find();
        $token =  $this->getToken($request->prjCode,$cameraData['configUuid']);
        // if(!$token) return result(FAIL,'','请先配置摄像头帐号appKey和appSecret,如已配置请检查是否有误');
   

        DB::startTrans();
        try {
           $update = DB::table('video_projectCamera')
           ->whereOr([
                [
                    ['projectCode','=',$request->prjCode],
                    ['isDelete','=',0],
                    ['uuid','=',$uuid]
                ],
                [
                    ['projectCode','=',$request->prjCode],
                    ['isDelete','=',0],
                    ['pid','=',$cameraData['id']]
                ],
           ])
           ->update([
               'isDelete'=>1,
               'connection'=>-1,
           ]);
            $messageg  = '删除失败,请重试';
            if($update&&$token){
                $res  = $this->sdk->destroy($cameraData);
                if($res['code']==200){
                    DB::commit();
                    return result(SUCCESS,'','删除成功');
                }
                $messageg = $res['messageg'];
            }
            DB::rollback();
        } catch (\Exception $e) {
          // 回滚事务
          DB::rollback();
        }
        return result(FAIL,'',$messageg);

    }


    /**
     * @Description: 获取有云录像的日期
     * @Author: Terry
     * @Date: 2024-08-13 23:30:37
     * @param {Request} $request
     */
    public function getCloudDate (Request $request){
        $data = $request->data;
        $prjCode = $request->prjCode;
        $uuid = $data['uuid'];
        $ipcData = DB::table('video_projectCamera')->where(['projectCode'=>$prjCode,'isDelete'=>0,'uuid'=>$uuid])->field(['gbNumber','gbChannel'])->find();
        if(!$ipcData) return result(FAIL,'','数据有误，获取失败');
        $sdk = new TengXunYun();
        $res = $sdk->getDate($ipcData);
        if($res)    return result(SUCCESS,$res);
        return result(FAIL,[],'该通道未开启云回放功能!');
    }


    /**
     * @Description: 获取云录像列表
     * @Author: Terry
     * @Date: 2024-08-13 23:30:52
     * @param {Request} $request
     */
    public function getCloudList(Request $request){
        $data = $request->data;
        $prjCode = $request->prjCode;
        $uuid = $data['uuid'];
        $ipcData = DB::table('video_projectCamera')->where(['projectCode'=>$prjCode,'isDelete'=>0,'uuid'=>$uuid])->field(['gbNumber','gbChannel'])->find();
        if(!$ipcData) return result(FAIL,'','数据有误，获取失败');
        $ipcData = array_merge($ipcData,$data);
        $sdk = new TengXunYun();
        $res = $sdk->getList($ipcData);
        if($res){
            $list = [];
            foreach ($res['VideoList'] as  $value) {
                $list[] = [
                    'startTime'=>date('H:i:s',$value['StartTime']),
                    'endTime'=>date('H:i:s',$value['EndTime']),
                    'duration'=>$this->formatSeconds($value['EndTime'] - $value['StartTime']),
                    'uuid'=>$value['InitID'],
                    'videoUrl'=>$value['VideoUrl'],
                ];
            }
            $returnData = [
                'count'=>$res['TotalCount'],
                'list'=>$list,
            ];
            return result(SUCCESS,$returnData);
        }
        return result(FAIL,[],'该通道未开启云回放功能!');
       
    }

    private function formatSeconds($seconds) {
        // 计算小时、分钟和秒数
        $hours = floor($seconds / 3600);
        $minutes = floor(($seconds % 3600) / 60);
        $seconds = $seconds % 60;
    
        // 格式化为 `HH:MM:SS` 格式
        return sprintf('%02d:%02d:%02d', $hours, $minutes, $seconds);
    }
    
    /**
     * @Descripttion: 获取token
     * @Author: Terry
     * @Date: 2021-09-28 20:00:59
     * @param {*}
     */    
    private function getToken($prjCode,$configUuid){
        // YS7Secret
        $data  = DB::table('video_projectCameraConfig')
        ->where(['projectCode'=>$prjCode,'uuid'=>$configUuid])
        ->field(['appKey','secret','productCode','projectId','type'])
        ->find();
        if(empty($data))return false;

        $type = $data['type'];
        $sdkName = "app\\video\\extend\\libs\\{$type}";
        $this->sdk = new $sdkName();
        $token  = $this->sdk->getToken($data['appKey'],$data['secret'],$data['productCode'],$data['projectId']);
        if(is_string($token)) return $token;
        return false;
    }

    
   
}
